/**    
* @Title: PlanEntrustEngine.java
* @Package: org.vdalf.gsgz.service
* @author vDalf 2020-09-26 17:47:24 下午5:47:24
* @Copyright © 2020 vDalf Block-Chain Foundation (In Preparation Non-Governmental Organization) All rights reserved.
*/
package org.vdalf.gsgz.service;

import java.math.BigDecimal;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicInteger;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.vdalf.gsgz.api.impl.OkexRestApi;
import org.vdalf.gsgz.entities.PlanEntrust;
import org.vdalf.gsgz.entities.UserData;
import org.vdalf.gsgz.enums.EnumActions;
import org.vdalf.gsgz.enums.EnumConditions;
import org.vdalf.gsgz.utils.MarketUtils;

import com.okcoin.commons.okex.open.api.bean.futures.param.Order;
import com.okcoin.commons.okex.open.api.bean.swap.param.PpOrder;

/**    
* @Title: PlanEntrustEngine.java
* @Package: org.vdalf.gsgz.service
* @Description: 
* @author vDalf 2020-09-26 17:47:24 下午5:47:24
*/
public class PlanEntrustEngine implements IPriceCommander{
	
	private static final Logger logger = LoggerFactory.getLogger(PlanEntrustEngine.class);

	private static final AtomicInteger ID_SEQ = new AtomicInteger();
	
	private OkexRestApi okexRestApi;
	
	public PlanEntrustEngine(OkexRestApi okexRestApi) {
		super();
		this.okexRestApi = okexRestApi;
	}

	public void start() {
		DataCenter.getInstance().addCommander(this);
	}
	
	@Override
	public void updatePrice(String market, BigDecimal price) {
		logger.info("最新价格变动：market={},price={}",market,price);
		synchronized (UserData.getInstance()) {
			Optional.ofNullable(UserData.getInstance().getPlanEntrusts().get(market)).ifPresent(c->{
				Optional.ofNullable(c.get(EnumConditions.小于)).ifPresent(m->{
					for(Iterator<Entry<BigDecimal, PlanEntrust>> iterator = m.entrySet().iterator();iterator.hasNext();) {
						Entry<BigDecimal, PlanEntrust> entry = iterator.next();
						if(price.compareTo(entry.getKey())<=0) {
							iterator.remove();//无论下单成功与否都先移除本计划 防止重复下单导致爆仓
							doEntrustByPlain(market, entry.getValue());
						}else {
							break;
						}
					}
				});
				Optional.ofNullable(c.get(EnumConditions.大于)).ifPresent(m->{
					for(Iterator<Entry<BigDecimal, PlanEntrust>> iterator = m.entrySet().iterator();iterator.hasNext();) {
						Entry<BigDecimal, PlanEntrust> entry = iterator.next();
						if(price.compareTo(entry.getKey())>=0) {
							iterator.remove();
							doEntrustByPlain(market, entry.getValue());
						}else {
							break;
						}
					}
				});
			});
		}
	}

	private void doEntrustByPlain(String market,PlanEntrust plan) {
		EnumActions action = EnumActions.getByCode(plan.getAction());
		if(action==null||action==EnumActions.无操作) {
			logger.info("本计划[{}]无可执行操作...",plan);
			return;
		}
		if(plan.getOrderVolume()!=null&&plan.getOrderVolume().compareTo(BigDecimal.ZERO)<=0) {
			logger.info("本计划[{}]无下单量可下单...",plan);
			return;
		}
		logger.info("触发计划委托:{}",plan);
		if(MarketUtils.isFuture(market)) {
			Order order = new Order();
			order.setinstrument_id(market);
			order.setClient_oid("F"+System.currentTimeMillis()+String.valueOf(ID_SEQ.addAndGet(1)));
			order.setType(EnumActions.getByCode(plan.getAction()).toOrderType("okex"));
			order.setOrder_type("0");
//			order.setType(Integer.valueOf(EnumActions.getByCode(plan.getAction()).toOrderType("okex")));
			order.setPrice(plan.getOrderPrice().toPlainString());
			order.setSize(String.valueOf(plan.getOrderVolume().intValue()));
			order.setMatch_price("0");
			try {
				this.okexRestApi.doOrder(order);
			} catch (Exception e) {
				logger.error("下单异常....",e);
			}
		}else if(MarketUtils.isSwap(market)) {
			PpOrder order = new PpOrder ();
			order.setInstrument_id(market);
			order.setClient_oid("S"+System.currentTimeMillis()+String.valueOf(ID_SEQ.addAndGet(1)));
			order.setType(EnumActions.getByCode(plan.getAction()).toOrderType("okex"));
			order.setOrder_type("0");
			order.setPrice(plan.getOrderPrice().toPlainString());
			order.setSize(String.valueOf(plan.getOrderVolume().intValue()));
			order.setMatch_price("0");
			try {
				this.okexRestApi.doOrder(order);
			} catch (Exception e) {
				logger.error("下单异常....",e);
			}
		}else
			throw new IllegalStateException("暂时仅支持交割合约和永续合约下单");
	}
	
	
}
